#include "timer.h"

uint8_t Frequency;

/*function:timer_group_get
 *feature:interior call function,get timer group.
 *input:pin: timer pin.
 *output:dat:timer group. 
 *time:2024/11/27
 */
static uint32_t timer_group_get(timer_index_enum INDEX)
{
    uint32_t timer_type;
    switch (INDEX)
    {
        case TIM0:   rcu_periph_clock_enable(RCU_TIMER0);   timer_type = TIMER0;    break;
        case TIM1:   rcu_periph_clock_enable(RCU_TIMER1);   timer_type = TIMER1;    break;
        case TIM2:   rcu_periph_clock_enable(RCU_TIMER2);   timer_type = TIMER2;    break;
        case TIM13:  rcu_periph_clock_enable(RCU_TIMER13);  timer_type = TIMER13;   break;
        case TIM14:  rcu_periph_clock_enable(RCU_TIMER14);  timer_type = TIMER14;   break;
        case TIM15:  rcu_periph_clock_enable(RCU_TIMER15);  timer_type = TIMER15;   break;
        case TIM16:  rcu_periph_clock_enable(RCU_TIMER16);  timer_type = TIMER16;   break;
    }
    return timer_type;
}

/*function:timer_channel_get
 *feature:interior call function,get timer channel.
 *input:pin: timer pin.
 *output:dat:timer channel. 
 *time:2024/11/27
 */
static uint16_t timer_channel_get(pwm_channel_enum pin)
{
    uint16_t channel_type;
    switch(pin & 0xF0)
    {
        case 0x00:    channel_type = TIMER_CH_0; break;  
        case 0x10:    channel_type = TIMER_CH_1; break;
        case 0x20:    channel_type = TIMER_CH_2; break;
        case 0x30:    channel_type = TIMER_CH_3; break;
    }
    return channel_type;
}

/*function:IRQ_type_get()
 *feature:IRQ type get.
 *input:pin: timer pin.
 *output:dat:IRQ type. 
 *time:2024/11/28
 */
static uint32_t IRQ_type_get(timer_index_enum INDEX)
{
    uint32_t irq_type;
    switch(INDEX)
    {
        case TIM1:  irq_type = TIMER1_IRQn;  break;
        case TIM2:  irq_type = TIMER2_IRQn;  break;
        case TIM13: irq_type = TIMER13_IRQn; break;
        case TIM14: irq_type = TIMER14_IRQn; break;
        case TIM15: irq_type = TIMER15_IRQn; break;
        case TIM16: irq_type = TIMER16_IRQn; break;
    }
    return irq_type;
}

/*function:timer_interrupt_init
 *feature:init timer to imterrupt.
 *input:pin: timer pwm pin(Select from the pwm_channel_enum enum of timer.h)
 *      prescaler:Timer pre-divider setting,It is usually set to the chip master frequency
 *      period:Timer period,Sets the value of the automatic reload register
 * output:none
 * e.g. timer_pwm_init(TIMER13_CH0, 20, 0.5);
 * time:2024/11/27
 */
void timer_interrupt_init(pwm_channel_enum pin, uint8_t pres, uint8_t priod)
{
    timer_parameter_struct timer_initpara;

    uint32_t timer_type, irq_type;
    timer_type = timer_group_get((timer_index_enum)(pin & 0x0F));
    irq_type = IRQ_type_get((timer_index_enum)(pin & 0x0F));
    timer_deinit(timer_type);

    timer_initpara.prescaler = pres - 1;
    timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection = TIMER_COUNTER_UP;
    timer_initpara.period = priod - 1;
    timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(timer_type, &timer_initpara);

    timer_interrupt_flag_clear(timer_type, TIMER_INT_UP);
    timer_interrupt_enable(timer_type, TIMER_INT_UP);
    nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
    nvic_irq_enable(irq_type, 1, 1);
    timer_enable(timer_type);
}

/*function:timer_pwm_init
 *feature:init timer pwm channel.
 *input:pin: timer pwm pin(Select from the pwm_channel_enum enum of timer.h)
 *      freq: timer pwm frequency (just input kHz)
 *      duty: timer pwm duty (Enter a value for the percentage, 0 ~ 1)
 * output:none
 * e.g. timer_pwm_init(TIMER13_CH0, 20, 0.5);
 * time:2024/11/27
 */
void timer_pwm_init(pwm_channel_enum pin, uint8_t freq, float duty)
{
    timer_oc_parameter_struct timer_ocintpara;
    timer_parameter_struct timer_initpara;

    uint16_t channel_type;
    uint8_t fre_div, period_temp;
    uint32_t timer_type;

    fre_div = FREQ(freq);
    period_temp = (uint8_t)(duty * fre_div);
    timer_type = timer_group_get((timer_index_enum)(pin & 0x0F));
    channel_type = timer_channel_get(pin);

    afio_init((gpio_pin_enum)((pin & 0xFFF000) >> 12), (gpio_af_enum)((pin & 0xF00) >> 8), GPO_PUSH_PULL); 
    timer_deinit(timer_type);

    timer_initpara.prescaler = 10 - 1;
    timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection = TIMER_COUNTER_UP;
    timer_initpara.period = 5000 - 1;
    timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(timer_type, &timer_initpara);

    timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
    timer_ocintpara.outputstate = TIMER_CCX_ENABLE;

    timer_channel_output_config(timer_type, channel_type, &timer_ocintpara);

    timer_channel_output_pulse_value_config(timer_type, channel_type, 0);
    timer_channel_output_mode_config(timer_type, channel_type, TIMER_OC_MODE_PWM0); 
    timer_channel_output_shadow_config(timer_type, channel_type, TIMER_OC_SHADOW_DISABLE);

    timer_auto_reload_shadow_enable(timer_type);
    timer_enable(timer_type);

    timer_autoreload_value_config(timer_type, fre_div);
    timer_channel_output_pulse_value_config(timer_type, channel_type, period_temp);



}

/*function:pwm_duty_set
 *feature:init timer pwm channel.
 *input:pin: timer pwm pin(Select from the pwm_channel_enum enum of timer.h)
 *      duty: timer pwm duty (Enter a value for the percentage, 0 ~ 1)
 * output:none
 * e.g. pwm_duty_set(TIMER13_CH0, 0.5);
 * time:2024/11/29
 */
void pwm_duty_set(pwm_channel_enum pin, float duty)
{
    uint32_t time_type;
    uint16_t channel_type;
    time_type = timer_group_get((timer_index_enum)(pin & 0x0F));
    channel_type = timer_channel_get(pin);
    timer_channel_output_pulse_value_config(timer_type, channel_type, (uint8_t)(FREQ(Frequency) * duty));
}

/*function:pwm_fre_set
 *feature:init timer pwm channel.
 *input:pin: timer pwm pin(Select from the pwm_channel_enum enum of timer.h)
 *      freq: timer pwm frequency (just input kHz)
 * output:none
 * e.g. pwm_fre_set(TIMER13_CH0, 20);
 * time:2024/11/29
 */
void pwm_fre_set(pwm_channel_enum pin, uint8_t freq)
{
    uint32_t time_type;
    time_type = timer_group_get((timer_index_enum)(pin & 0x0F));
    timer_autoreload_value_config(time_type, FREQ(freq));
}